<?php
declare(strict_types=1);

namespace App\AdminApi\Module\Admin\Command;

use App\AdminApi\Module\Admin\Service\UserService;
use App\Common\Guard\AdminGuard;
use App\Common\Model\Admin\UserModel;
use App\Sys;
use Hyperf\Command\Annotation\Command;
use Psr\SimpleCache\InvalidArgumentException;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Zms\Unit\Str;

#[Command]
class AdminCommand extends \Hyperf\Command\Command
{

    const CHOICE = ['修改管理员密码', '解除账号锁定', '生成登录授权码'];
    /**
     * 执行的命令行
     *
     * @var null|string
     */
    protected ?string $name = 'app:admin';


    public function __construct(string $name = null)
    {
        parent::__construct($name);
        $this->setDescription('后台系统命令:支持' . implode(',', self::CHOICE));
    }

    public function handle()
    {
        $choice = array_merge(['取消'], self::CHOICE);
        $handle = $this->choice('请选择操作', $choice, 0);
        switch ($handle) {
            case '修改管理员密码':
                $this->editAdministratorsPassword($this->input, $this->output);
                break;
            case '解除账号锁定':
                $this->unlockAccount($this->input, $this->output);
                break;
            case '生成登录授权码':
                $this->genLoginCode($this->input, $this->output);
                break;
            case '取消';
                $this->output->warning('操作已取消');
                break;
        }
    }


    /**
     * 修改管理员密码
     * @param InputInterface $input
     * @param OutputInterface $output
     * @return void
     */
    private function editAdministratorsPassword(InputInterface $input, OutputInterface $output): void
    {
        $result = $this->LoadUserId($input, $output);
        if (gettype($result) === 'string') {
            $this->output->warning($result);
            return;
        }
        /**
         * @var AdminGuard $account
         */
        $account = AdminGuard::where(['id' => $result])->first();
        inputpwd:
        $pwd = $this->output->ask('请输入新密码');
        if (!(is_string($pwd) && strlen($pwd) > 0)) {
            goto inputpwd;
        }


        $error = Sys::container(UserService::class)->checkPassword($pwd);
        if ($error !== true) {
            $this->output->warning($error);
            goto inputpwd;
        }

        inputpwd2:
        $pwd2 = $this->output->ask('请再次确认密码');
        if (!(is_string($pwd2) && strlen($pwd2) > 0)) {
            goto inputpwd2;
        }
        if ($pwd !== $pwd2) {
            $this->output->warning('两次密码不一致');
            goto inputpwd;
        }

        $account->secret_key = $account->generateSecretKey();
        $account->password = $account->generatePassword($pwd, $account->secret_key);
        if ($account->save()) {
            $this->output->success("账号{$account->account}密码已修改为:$pwd");
        } else {
            $this->output->error("账号{$account->account}密码修改失败");
        }
    }


    /**
     * 解除账号锁定
     * @param InputInterface $input
     * @param OutputInterface $output
     * @return void
     */
    private function unlockAccount(InputInterface $input, OutputInterface $output): void
    {
        $result = $this->LoadUserId($input, $output);
        if (gettype($result) === 'string') {
            $this->output->warning($result);
            return;
        }
        /**
         * @var AdminGuard $account
         */
        $account = AdminGuard::where(['id' => $result])->first();
        $account->error = 0;
        $account->locking = 0;
        if ($account->save()) {
            $this->output->success("账号{$account->account}密码已解除锁定");
        } else {
            $this->output->error("账号{$account->account}密码修改失败");
        }
    }


    /**
     * 生成登录授权码
     * @param InputInterface $input
     * @param OutputInterface $output
     * @return void
     */
    private function genLoginCode(InputInterface $input, OutputInterface $output): void
    {

        $result = $this->LoadUserId($input, $output);
        if (gettype($result) === 'string') {
            $this->output->warning($result);
            return;
        }
        $state = Sys::container(UserService::class)->checkAccountStatus((int)$result);
        if ($state !== true) {
            $this->output->error($state);
            return;
        }
        $code = Str::md5_16(time(), rand(1000, 9999), rand(1000, 9999));
        try {
            Sys::cache()->set($code, $result, 180);
            $this->output->success("您的授权码为:【{$code}】,有效期180秒");
        } catch (InvalidArgumentException) {
            $this->output->error('生成授权码失败');
        }

    }


    /**
     * @param InputInterface $input
     * @param OutputInterface $output
     * @return int|string
     */
    private function LoadUserId(InputInterface $input, OutputInterface $output): int|string
    {
        $users = UserModel::select(['id', 'nickname', 'account', 'status', 'last_login', 'locking'])->get()->toArray();
        if (count($users) === 0) {
            return '没有可使用的账号';
        }
        $list = [];
        foreach ($users as $item) {
            $list[] = [
                $item['id'], $item['nickname'], $item['account'], $item['status'] ? '使用中' : '已禁用',
                $item['last_login'] ? date("Y-m-d H:i:s", $item['last_login']) : '',
                $item['locking'] > time() ? (date('Y-m-d H:i:s', $item['locking'])) : ''
            ];
        }

        $table = new Table($output);
        $table->setHeaders(['id', '账号', '昵称', '状态', '上次登录', '锁定状态'])->setRows($list);
        $table->render();

        inputid:
        $id = $this->output->ask('请输入要生成登录授权码的账号ID,输入0则代表取消操作');
        if (!(is_string($id) && strlen($id) > 0 && is_numeric($id))) {
            goto inputid;
        }
        $id = intval($id);
        if ($id === 0) {
            return '操作已取消';
        }
        return $id;
    }
}